package com.wenjiang.aspect;


import com.google.common.util.concurrent.RateLimiter;
import com.wenjiang.common.annotation.LimitFlow;
import com.wenjiang.common.exception.SystemBusyException;
import com.wenjiang.common.exception.SystemException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * 限流切面
 */
@Component
@Aspect
public class LimitAspect {

    // 定义一个concurrent hashmap用来存放线流的集合
    private ConcurrentHashMap<String, RateLimiter> concurrentHashMap = new ConcurrentHashMap<>();


    /**
     * 对带有 LimitFlow 进行拦截
     */
    @Pointcut(value = "@annotation(com.wenjiang.common.annotation.LimitFlow)")
    private void LimitAspect(){

    }


    @Around(value = "LimitAspect()")
    public  Object around(ProceedingJoinPoint JoinPoint) throws Throwable {
        // 获取切点上的方法
        MethodSignature signature =  (MethodSignature) JoinPoint.getSignature();

        // 获取方法上的注解(私有的也破解)
        LimitFlow limitFlow = signature.getMethod().getDeclaredAnnotation(LimitFlow.class);

        // 获取注解的属性的值（判断有没有初始化）
        RateLimiter rateLimiter = concurrentHashMap.get(limitFlow.name());
        if(rateLimiter==null){
            // 创造一个新的限制器 每秒创建相应的参数  超过一定时间直接销毁
            rateLimiter = RateLimiter.create(limitFlow.token());
            concurrentHashMap.put(limitFlow.name(), rateLimiter);

        }

        //判断有没有超过限制
        if(!rateLimiter.tryAcquire(1, limitFlow.timeout(),TimeUnit.SECONDS)){
           throw  new SystemBusyException();
        }

        //放行
        return JoinPoint.proceed();


    }

}
